interface Named12 {
    name: string;
}

let x12: Named12;
// y's inferred type is { name: string; location: string; }
let y12 = { name: 'Alice', location: 'Seattle' };
x12 = y12;
console.log(x12)
// 这里要检查y是否能赋值给x，编译器检查x中的每个属性，看是否能在y中也找到对应属性。 在这个例子中，y必须包含名字是name的string类型成员。y满足条件，因此赋值正确。



// 函数参数双向协变
// 当比较函数参数类型时，只有当源函数参数能够赋值给目标函数或者反过来时才能赋值成功。 这是不稳定的，因为调用者可能传入了一个具有更精确类型信息的函数，但是调用这个传入的函数的时候却使用了不是那么精确的类型信息。 实际上，这极少会发生错误，并且能够实现很多JavaScript里的常见模式。




// 枚举
// 枚举类型与数字类型兼容，并且数字类型与枚举类型兼容。不同枚举类型之间是不兼容的。比如，
//
enum Status345 { Ready, Waiting };
enum Color345 { Red, Blue, Green };
let status355 = Status345.Ready;
// status = Color.Green;  // Error


//类
// 类与对象字面量和接口差不多，但有一点不同：类有静态部分和实例部分的类型。 比较两个类类型的对象时，只有实例的成员会被比较。 静态成员和构造函数不在比较的范围内。

class Animal345 {
    feet345: number;
    constructor(name: string, numFeet: number) {
        this.feet345 = numFeet
    }
}
class Size345 {
    feet345: number;
    constructor(numFeet: number) {
        this.feet345 = numFeet
    }
}
let a345: Animal345 = new Size345(1);
let s345: Size345 = new Animal345("猫",21);
a345 = s345; // true
s345 = a345; // true



// 类的私有成员和受保护成员
// 类的私有成员和受保护成员会影响兼容性。 当检查类实例的兼容时，如果目标类型包含一个私有成员，那么源类型必须包含来自同一个类的这个私有成员。 同样地，这条规则也适用于包含受保护成员实例的类型检查。 这允许子类赋值给父类，但是不能赋值给其它有同样类型的类。


// 泛型
//因为TypeScript是结构性的类型系统，类型参数只影响使用其做为类型一部分的结果类型。比如，
interface Empty8<T> {
}
let x88: Empty8<number> = new class implements Empty8<number> {};
let y88: Empty8<string> = new class implements Empty8<string> {};

x88 = y88;  // OK, because y matches structure of x
// 上面代码里，x88和y88是兼容的，因为它们的结构使用类型参数时并没有什么不同。 把这个例子改变一下，增加一个成员，就能看出是如何工作的了：
/*interface NotEmpty99<T> {
    data: T;
}
let x99: NotEmpty99<number> = new class implements NotEmpty99<number> {
    data: number;
};
let y99: NotEmpty99<string> = new class implements NotEmpty99<string> {
    data: string;
};*/

// x99 = y99;  // Error, because x and y are not compatibl



// 对于没指定泛型类型的泛型参数时，会把所有泛型参数当成any比较。 然后用结果类型进行比较，就像上面第一个例子
let identity212:<T>(y: T)=> T = <T>(x: T): T => x
let reverse212:<U>(y: U)=> U = <U>(y: U): U => y
identity212 = reverse212;  // OK, because (x: any) => any matches (y: any) => any


































